package com.csoa.community.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.util.Log;

import com.csoa.community.bean.SoapBody;
import com.csoa.community.net.ErrorMsg;
import com.csoa.community.singletons.GlobalVars;

public class HttpUtils {
	

	private static HttpUtils _inst = new HttpUtils();

	public static HttpUtils getInst() {
		return _inst;
	}

	private HttpUtils() {
	}

	public String getBytes(String url, String method, String paramXML,String charset)throws ErrorMsg {

		URL uri;
		HttpURLConnection conn = null;
		String result="";
		try {
			uri = new URL(url);
			conn = (HttpURLConnection) uri.openConnection();
			conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
			conn.setRequestProperty("Content-Length", String.valueOf(paramXML.getBytes().length));
			conn.setRequestProperty("SOAPAction", "http://tempuri.org/IArchives/" + method);
			conn.setRequestMethod("POST");
//			conn.setReadTimeout(5000);
//			conn.setConnectTimeout(5000);
			conn.setReadTimeout(10000);
			conn.setConnectTimeout(10000);

			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.connect();

			OutputStream out = conn.getOutputStream();
			out.write(paramXML.getBytes());
			out.close();
			int code = conn.getResponseCode();
			System.out.println("接口状态：" + code);
			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
//				InputStream in = conn.getInputStream();
//				byte[] retBytes = new byte[in.available()];
//				in.read(retBytes);
//				return retBytes;//返回的数据不完全
				BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), charset));
				String inputline = null;
				while((inputline = reader.readLine()) != null) {
					result += inputline + "\n";
				}
				reader.close();//为什么数据多了返回的数据接收不完全
				return result;
			}
		} catch (MalformedURLException e) {
			throw new ErrorMsg("network.url.format");
		} catch (IOException e) {
			throw new ErrorMsg("network.io.exception");
		} finally {
			if (conn != null) {
				conn.disconnect();
			}
		}
		return null;
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.encoding"
	 */
	public String getString(Context c, String url, String charset) throws ErrorMsg {
		if (charset == null || charset.trim().length() == 0) {
			charset = "utf-8";
		}
		try {
			return new String(getBytes(c, url), charset);
		} catch (UnsupportedEncodingException e) {
			throw new ErrorMsg("network.encoding");
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.encoding"
	 */
	public String getStringBySoap(Context c, String url, SoapBody soap, String charset) throws ErrorMsg {
		if (charset == null || charset.trim().length() == 0) {
			charset = "utf-8";
		}
		if (url == null || "".equals(url)) {
			return null;
		}
		try {
			return getBytes(url, soap.getMethod(), soap.toString(), charset);
		} catch (Exception e) {
			throw new ErrorMsg("network.encoding");
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.entity.to.bytearray"
	 */
	public byte[] getBytes(Context c, String url) throws ErrorMsg {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		try {
			return EntityUtils.toByteArray(getRequest(url, null, c, false, httpClient));
		} catch (IOException e) {
			throw new ErrorMsg("network.entity.to.bytearray");
		} finally {
			if (httpClient != null) {
				httpClient.getConnectionManager().shutdown();
			}
		}
	}

	public byte[] getBytes(Context c, String url, boolean isPost) throws ErrorMsg {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		try {
			return EntityUtils.toByteArray(getRequest(url, null, c, isPost, httpClient));
		} catch (IOException e) {
			throw new ErrorMsg("network.entity.to.bytearray");
		} finally {
			if (httpClient != null) {
				httpClient.getConnectionManager().shutdown();
			}
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.entity.obtained" "network.entity.create.stream"
	 */
	public InputStream getInputStream(Context c, String url) throws ErrorMsg {

		DefaultHttpClient httpClient = new DefaultHttpClient();
		try {
			return getRequest(url, null, c, false, httpClient).getContent();
		} catch (IllegalStateException e) {
			throw new ErrorMsg("network.entity.obtained");
		} catch (IOException e) {
			throw new ErrorMsg("network.entity.create.stream");
		} finally {
			if (httpClient != null) {
				httpClient.getConnectionManager().shutdown();
			}
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.encoding"
	 */
	public String getString(Context c, String url, Map<String, String> post, String charset) throws ErrorMsg {
		if (charset == null || charset.trim().length() == 0) {
			charset = "utf-8";
		}
		try {
			return new String(getBytes(c, url, post), charset);
		} catch (UnsupportedEncodingException e) {
			throw new ErrorMsg("network.encoding");
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.entity.to.bytearray"
	 */
	public byte[] getBytes(Context c, String url, Map<String, String> post) throws ErrorMsg {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		try {
			return EntityUtils.toByteArray(getRequest(url, post, c, httpclient));
		} catch (IOException e) {
			throw new ErrorMsg("network.entity.to.bytearray");
		} finally {
			if (httpclient != null) {
				httpclient.getConnectionManager().shutdown();
			}
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.entity.obtained" "network.entity.create.stream"
	 */
	public InputStream getInputStream(Context c, String url, Map<String, String> post) throws ErrorMsg {
		DefaultHttpClient httpclient = new DefaultHttpClient();
		try {
			return getRequest(url, post, c, httpclient).getContent();
		} catch (IllegalStateException e) {
			throw new ErrorMsg("network.entity.obtained");
		} catch (IOException e) {
			throw new ErrorMsg("network.entity.create.stream");
		} finally {
			if (httpclient != null) {
				httpclient.getConnectionManager().shutdown();
			}
		}
	}
	
	
	
	
	public String getStringByWcf(String method,List<BasicNameValuePair> params) throws ErrorMsg{
       return getStringByWcf(method,params,GlobalVars.serviceDocURL,GlobalVars.soapDocAction);
	}
	
	
	public String getStringByWcf(String method,List<BasicNameValuePair> params,String url,String soap) throws ErrorMsg{
        SoapObject request = new SoapObject(GlobalVars.serviceNameSpace, method);
        if(params != null) {
        	for (int i = 0, len = params.size(); i < len; i++) {
        		request.addProperty(params.get(i).getName(), params.get(i)
        				.getValue());
        	}
        	
        }
        // 获得序列化的Envelope
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                SoapEnvelope.VER10);
        envelope.dotNet = true;
//        envelope.bodyOut = request;
        envelope.setOutputSoapObject(request);

        // Android传输对象
        HttpTransportSE transport = new HttpTransportSE(url);
        transport.debug = true;
        // 调用WebService
        try {
            transport.call(soap + method, envelope);
        } catch (IOException e) {
        	throw new ErrorMsg("network.entity.create.stream");
        } catch (XmlPullParserException e) {
        	throw new ErrorMsg("network.entity.create.stream");
        }
        
        String str = "";
        try {
        	if(envelope.getResponse() != null) {
        		str = envelope.getResponse().toString();
        	}
        	Log.i("msg", str);
        	
            if (str != null) {
                return str;
            }
        } catch (SoapFault e) {
        	throw new ErrorMsg("network.entity.create.stream");
        }

        return null;
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.url.format" "network.uri.syntax"
	 *             "network.http.protocol" "network.io.exception"
	 */
	private HttpEntity getRequest(String uriAPI, String post, Context ctx, boolean isPost, DefaultHttpClient httpclient)
			throws ErrorMsg {
		if (uriAPI == null || "".equals(uriAPI)) {
			return null;
		}
		httpclient = buildClient(ctx);
		StringEntity entity;
		URL url;
		try {
			url = new URL(uriAPI);
			int port = url.getPort();
			if (port == -1)
				port = 80;
			URI uri = new URI(url.getProtocol(), url.getHost() + ":" + port, url.getPath(), url.getQuery(), null);
			HttpResponse rsp = null;
			if (isPost) {
				HttpPost req = null;
				req = new HttpPost(uri);
				entity = new StringEntity(post, "utf-8");
				req.setEntity(entity);
				rsp = httpclient.execute(req);
			} else {
				HttpGet req = null;
				req = new HttpGet(uri);
				rsp = httpclient.execute(req);
			}

			if (rsp.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
				return rsp.getEntity();
			} else if (rsp.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
				throw new ErrorMsg("network.serverError");
			} else {
				throw new ErrorMsg("network");
			}
		} catch (MalformedURLException e) {
			throw new ErrorMsg("network.url.format");
		} catch (URISyntaxException e) {
			throw new ErrorMsg("network.uri.syntax");
		} catch (UnsupportedEncodingException e) {
			throw new ErrorMsg("network.encoding");
		} catch (ClientProtocolException e) {
			throw new ErrorMsg("network.http.protocol");
		} catch (IOException e) {
			throw new ErrorMsg("network.io.exception");
		}
	}

	/**
	 * 
	 * @throws ErrorMsg
	 *             "network.url.format" "network.uri.syntax"
	 *             "network.http.protocol" "network.io.exception"
	 */
	private HttpEntity getRequest(String uriAPI, Map<String, String> requestValues, Context ctx,
			DefaultHttpClient httpclient) throws ErrorMsg {
		if (uriAPI == null || "".equals(uriAPI)) {
			return null;
		}
		try {

			httpclient = buildClient(ctx);
			URL url = new URL(uriAPI);
			int port = url.getPort();
			if (port == -1)
				port = 80;
			URI uri = new URI(url.getProtocol(), url.getHost() + ":" + port, url.getPath(), url.getQuery(), null);
			HttpResponse rsp = null;

			HttpPost req = null;

			List<NameValuePair> list = new ArrayList<NameValuePair>();
			for (Map.Entry<String, String> entry : requestValues.entrySet()) {// �����?�ֶ�����
				list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}

			req = new HttpPost(uri);
			req.setEntity(new UrlEncodedFormEntity(list, HTTP.UTF_8));
			rsp = httpclient.execute(req);
			if (rsp.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
				return rsp.getEntity();
			} else if (rsp.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
				throw new ErrorMsg("network.serverError");
			} else {
				throw new ErrorMsg("network");
			}
		} catch (MalformedURLException e) {
			throw new ErrorMsg("network.url.format");
		} catch (URISyntaxException e) {
			throw new ErrorMsg("network.uri.syntax");
		} catch (UnsupportedEncodingException e) {
			throw new ErrorMsg("network.encoding");
		} catch (ClientProtocolException e) {
			throw new ErrorMsg("network.http.protocol");
		} catch (IOException e) {
			throw new ErrorMsg("network.io.exception");
		}
	}

	private DefaultHttpClient buildClient(Context ctx) {

		HttpHost proxy = null;
		APNType apnType = getCurrentUsedAPNType(ctx);
		if (APNType.CTWAP.equals(apnType)) {// ����
			proxy = new HttpHost(CTPROXY, Integer.parseInt(PROT));
		} else if (APNType.CMWAP.equals(apnType)) {// �ƶ�
			proxy = new HttpHost(CMPROXY, Integer.parseInt(PROT));
		}
		HttpParams httpParameters = new BasicHttpParams();

		int timeoutConnection = 1000 * 10;

		HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
		int timeoutSocket = 1000 * 10;
		HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
		DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters);
		// û��wifi�Ͳ����ô���
		if (!testWifi(ctx)) {
			if (proxy != null) {
				httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
			}
		}

		return httpclient;
	}

	public static final String tag = HttpUtils.class.getSimpleName();

	public boolean testWifi(Context ctx) {
		ConnectivityManager mConnectivity = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo info = mConnectivity.getActiveNetworkInfo();
		if (info == null || !mConnectivity.getBackgroundDataSetting()) {
			Log.d(tag, "!mConnectivity.getBackgroundDataSetting()" + mConnectivity.getBackgroundDataSetting());
			return false;
		}
		int netType = info.getType();
		int netSubType = info.getSubtype();
		Log.d(tag, "netType:" + netType + " netSubType:" + netSubType);
		if (ConnectivityManager.TYPE_WIFI == netType) {
			Log.d(tag, "TYPE_WIFI");
			return info.isConnectedOrConnecting();
		}
		return false;
	}

	/**
	 * ���������?
	 */
	public enum APNType {
		CMWAP, CMNET, Unknow, CTWAP, CTNET, _3GNET, _3GWAP;
	}

	public static final String CMPROXY = "10.0.0.172";
	public static final String CTPROXY = "10.0.0.200";
	public static final String PROT = "80";
	public static Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn");

	// ��ȡ���������?
	private APNType getCurrentUsedAPNType(Context ctx) {
		Log.d(tag, "getCurrentUsedAPNType");
		try {
			ContentResolver cr = ctx.getContentResolver();
			Cursor cursor = cr.query(PREFERRED_APN_URI, new String[] { "_id", "name", "apn", "proxy", "port" }, null,
					null, null);

			cursor.moveToFirst();
			if (cursor.isAfterLast()) {
				return APNType.Unknow;
			}
			String id = cursor.getString(0);
			String name = cursor.getString(1);
			String apn = cursor.getString(2);
			String proxy = cursor.getString(3);
			String _prot = cursor.getString(4);
			// if (!StringUtils.isEmpty(proxy)) {
			// String proxyAddress = proxy;
			// }
			// if (!StringUtils.isEmpty(_prot)) {
			// String proxyProt = _prot;
			// }
			Log.d(tag, id + " proxy:" + proxy + " prot:" + _prot + " apn:" + apn);
			cursor.close();
			if (// "1".equals(id) || //���ǵ���1Ϊctwap,2Ϊctnet
			(("CTWAP".equals(apn.toUpperCase()) || "CTWAP".equals(name.toUpperCase())) && !StringUtils.isEmpty(proxy) && !StringUtils
					.isEmpty(_prot)))
				return APNType.CTWAP;
			else if (// "2".equals(id) ||
			(("CTNET".equals(apn.toUpperCase()) || "CTNET".equals(name.toUpperCase())) && StringUtils.isEmpty(proxy) && StringUtils
					.isEmpty(_prot)))
				return APNType.CTNET;
			else if (("CMWAP".equals(apn.toUpperCase()) || "CMWAP".equals(name.toUpperCase()))
					&& !StringUtils.isEmpty(proxy) && !StringUtils.isEmpty(_prot))
				return APNType.CMWAP;
			else if (("CMNET".equals(apn.toUpperCase()) || "CMNET".equals(name.toUpperCase()))
					&& StringUtils.isEmpty(proxy) && StringUtils.isEmpty(_prot))
				return APNType.CMNET;
			else if (("3GWAP".equals(apn.toUpperCase()) || "3GWAP".equals(name.toUpperCase()))
					&& !StringUtils.isEmpty(proxy) && !StringUtils.isEmpty(_prot))
				return APNType._3GWAP;
			else if (("3GNET".equals(apn.toUpperCase()) || "3GNET".equals(name.toUpperCase()))
					&& StringUtils.isEmpty(proxy) && StringUtils.isEmpty(_prot))
				return APNType._3GNET;
			else
				return APNType.Unknow;
		} catch (Exception ep) {
			Log.e(tag, "getCurrentUsedAPNTypeException");
			return APNType.Unknow;
		}
	}

}
